/*-+-*****************************************************************************
 Copyright (C) 2009-2012 Oceanside Software Corporation (R)
 Dallas, Texas

 Author       : Jason T. Brower
 Purpose      : This file is part of a point-of-sale software package
                originally written for Table-Service Restaurants.
              
 Date         : July 8th of 2012
              
 History      : The application that this software file belongs to was 
                written over a 3-Year period.  The first version was written
                in C# .Net 3.5 using Windows Forms.  Being new to .Net at
                the time, I soon learned of Windows Presentation Foundation,
                liked the graphics capabilities and databinding so I
                migrated to WPF.  When the .Net 4.0 framework was released
                the application was migrated from 3.5 to 4.0. Now today,
                .Net 4.5 RC is out and I was already in process of migrating
                before I made this public.
                
Excuse Me     : Please excuse the coding style, it is not representative of
                my typical work.  During the three years I was under a very
                tight budget, constantly running out of funding and was 
                working 18 hour days hyped up on 5-Hour Energy.  The 
                design is not textbook.  It is monolythic because of
                previous issues I will not get into.  There are few comments
                in the code and the ones that are there may be incorrect.
                
What it is not: This is not the exact version that I took through PA-DSS 2.0
                nor is it the exact version running at my customer sites.
                I removed some details for security purposes including some
                encryption algorithms.  The reporting was removed because
                I was including a third party library that cannot be 
                published with this Open Source.
                
What it is    : This application has been running at high volume restaraunts
                for over a year.  It never freezes, crashes or does anything
                unexpected.  So long as it is built, installed and configured
                correctly, it is a strong system that we can all enhance.

Contact       : Please note that I can no longer work for free.  However, you
                can reach me at information@oceansidesw.com.                                                      

*********************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Data.Objects.DataClasses;
#if _LOCALDB
  using Oceanside.LocalDB;
#else
using Oceanside.RemoteDB;
#endif
namespace Oceanside
{
    static class SplitBindings
    {
        private static int _seatPivotIndex = 0;
        private static int _selectedSeatIndex = 0;

        public static int SelectedSeatIndex
        {
            get { return SplitBindings._selectedSeatIndex; }
            set { SplitBindings._selectedSeatIndex = value; }
        }
        private static int _custTicketScrollIndex = -1;
        private static List<FlatButton_52_58> _seatButtonsList = null;
        private static SALE _selectedSale = null;
        public static SALE SelectedSale
        {
            get { return _selectedSale; }
            set { _selectedSale = value; }
        }

        private static int _seatPivotIndex2 = 0;
        private static int _selectedSeatIndex2 = 0;

        public static int SelectedSeatIndex2
        {
            get { return SplitBindings._selectedSeatIndex2; }
            set { SplitBindings._selectedSeatIndex2 = value; }
        }
        private static int _custTicketScrollIndex2 = -1;
        private static List<FlatButton_52_58> _seatButtonsList2 = null;
        private static SALE _selectedSale2 = null;
        public static SALE SelectedSale2
        {
            get { return _selectedSale2; }
            set { _selectedSale2 = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public enum SPLITMODE
        {
            SEAT,
            CHECK
        }

        public static void MoveSaleToNewSeat(SALE saleToMove, int seat)
        {
            SALE sale = saleToMove;
            bool canMove = true;
            if (saleToMove.CountOrdered > 1)
            {
                HowManyBox hmb = new HowManyBox();
                hmb.ShowDialog();
                if (HowManyBox.LastNumberSelection > 0 && HowManyBox.LastNumberSelection <= saleToMove.CountOrdered)
                {
                    if (HowManyBox.LastNumberSelection == saleToMove.CountOrdered)
                    {
                        sale = saleToMove;
                    }
                    else
                    {
                        sale = SALE.SeparateSale(saleToMove, true, HowManyBox.LastNumberSelection);
                    }
                }
                else
                {
                    canMove = false;
                }
            }

            if (canMove)
            {
                int originalSeatNo = sale.OwningSeatNumber;

                ///Move the product to the new seat and renumber the sequence for the new
                ///seat.
                List<SALE> newSeatsSales = SHIFT.SelectedOrder.GetSeatsSales(seat).ToList();
                int index = newSeatsSales.Count() + 1;
                sale.SeatSequenceNumber = index;
                sale.OwningSeatNumber = seat;
                index++;

                List<SALE> modifierSales = sale.MODSALES.OrderBy(s => s.SeatSequenceNumber).ToList();
                foreach (SALE s in modifierSales)
                {
                    s.SeatSequenceNumber = index;
                    s.OwningSeatNumber = seat;
                    index++;
                }

                ///Now we need to renumber the sequence for the old seat.  The will still be in the correct order
                ///but there will be big gaps in the numbers that will cause issues later if we don't adjust them
                ///now.
                List<SALE> oldSeatsSales = SHIFT.SelectedOrder.GetSeatsSales(originalSeatNo).ToList();
                index = 1;
                foreach (SALE s in oldSeatsSales)
                {
                    s.SeatSequenceNumber = index;
                    index++;
                }

                SHIFT.GlobalContext.SaveChanges();
            }
        }

        public static bool MoveSaleToNewCheck(SALE saleToMove, int check, bool promptForCount = true)
        {
            SALE sale = saleToMove;
            bool canMove = true;
            if (saleToMove != null)
            {
                try
                {
                    if (promptForCount)
                    {
                        if (saleToMove.CountOrdered > 1)
                        {
                            HowManyBox hmb = new HowManyBox();
                            hmb.ShowDialog();
                            if (HowManyBox.LastNumberSelection > 0 && HowManyBox.LastNumberSelection <= saleToMove.CountOrdered)
                            {

                                decimal unpaid = SHIFT.SelectedOrder.CheckUnpaidGrandTotal(saleToMove.OwningCheckNumber);

                                if ((unpaid - (saleToMove.CountOrdered * (saleToMove.ActualPrice - (saleToMove.ActualPrice * saleToMove.DiscountRate))) < 0))
                                {
                                    canMove = false;
                                    UMD.ShowGuiMessageSTASafe_NOTHROW("You cannot remove items from a check when it forces a balance owed to the customer.");
                                }
                                else
                                {
                                    if (HowManyBox.LastNumberSelection == saleToMove.CountOrdered)
                                    {
                                        sale = saleToMove;
                                    }
                                    else
                                    {
                                        sale = SALE.SeparateSale(saleToMove, true, HowManyBox.LastNumberSelection);
                                    }
                                }
                            }
                            else
                            {
                                UMD.ShowGuiMessageSTASafe_NOTHROW("You must select an amount greater than zero and less than or equal to "
                + saleToMove.CountOrdered + " for the currently selected product.");
                                canMove = false;
                            }
                        }
                        else
                        {
                            decimal unpaid = SHIFT.SelectedOrder.CheckUnpaidGrandTotal(saleToMove.OwningCheckNumber);

                            if (unpaid - (saleToMove.ActualPrice - (saleToMove.ActualPrice * saleToMove.DiscountRate)) < 0)
                            {
                                canMove = false;
                                UMD.ShowGuiMessageSTASafe_NOTHROW("You cannot remove items from a check when it forces a balance owed to the customer.");
                            }
                        }
                    }
                    if (canMove)
                    {
                        int originalCheckNo = sale.OwningCheckNumber;

                        ///Move the product to the new seat and renumber the sequence for the new
                        ///seat.
                        List<SALE> newChecksSales = SHIFT.SelectedOrder.GetChecksSales(check);
                        int index = newChecksSales.Count() + 1;
                        sale.CheckSequenceNumber = index;
                        sale.OwningCheckNumber = check;
                        index++;

                        try
                        {
                            List<SALE> modifierSales = sale.MODSALES.OrderBy(s => s.CheckSequenceNumber).ToList();
                            foreach (SALE s in modifierSales)
                            {
                                s.CheckSequenceNumber = index;
                                s.OwningCheckNumber = check;
                                index++;
                            }
                        }
                        catch (Exception ex)
                        {
                            ///THIS IS TEMP CODE TO FIND A BUG THAT NOBODY COMPLAINS ABOUT
                            Logging.LogMessage("MOVE SALE TO NEW CHECK IN MOD SALES");
                            if (sale != null)
                            {
                                Logging.LogMessage("SALE ID = " + sale.Id);
                                Logging.LogMessage("USER = " + SHIFT.Current.User.Id);
                                Logging.LogMessage("ORDER = " + SHIFT.SelectedOrder.Id);
                            }
                            Logging.LogException(ex);
                        }

                        ///Now we need to renumber the sequence for the old seat.  The will still be in the correct order
                        ///but there will be big gaps in the numbers that will cause issues later if we don't adjust them
                        ///now.
                        List<SALE> oldChecksSales = SHIFT.SelectedOrder.GetChecksSales(originalCheckNo);
                        index = 1;
                        foreach (SALE s in oldChecksSales)
                        {
                            s.CheckSequenceNumber = index;
                            index++;
                        }

                        SHIFT.GlobalContext.SaveChanges();
                    }
                }
                catch (Exception ex)
                {
                    ///THIS IS TEMP CODE TO FIND A BUG THAT NOBODY COMPLAINS ABOUT
                    try
                    {
                        Logging.LogMessage("MOVE SALE TO NEW CHECK");
                        if (sale != null)
                        {
                            Logging.LogMessage("SALE ID = " + sale.Id);
                            Logging.LogMessage("USER = " + SHIFT.Current.User.Id);
                        }
                        Logging.LogException(ex);
                    }
                    catch (Exception) { }
                }
            }
            else
            {
                Logging.LogMessage("SALE TO MOVE TO NEW CHECK WAS NULL");
            }
            return canMove;
        }
        /// <summary>
        /// Keep track of what mode this page is in.
        /// </summary>
        public static SPLITMODE CurrentFormMode = SPLITMODE.SEAT;

        /// <summary>
        /// Constructor
        /// </summary>
        public static void Init()
        {
            ///Make sure to update the ticket index when it is clicked.
            Oceanside.SplitWindow.CustomerTicketListView.SelectionChanged +=
                new SelectionChangedEventHandler(CustomerTicketListView_SelectionChanged);

            Oceanside.SplitWindow.CustomerTicketListView2.SelectionChanged +=
                new SelectionChangedEventHandler(CustomerTicketListView2_SelectionChanged);

            _seatButtonsList = new List<FlatButton_52_58>(4);
            _seatButtonsList.Add(Oceanside.SplitWindow.SeatPosition1);
            _seatButtonsList.Add(Oceanside.SplitWindow.SeatPosition2);
            _seatButtonsList.Add(Oceanside.SplitWindow.SeatPosition3);
            _seatButtonsList.Add(Oceanside.SplitWindow.SeatPosition4);

            _seatButtonsList2 = new List<FlatButton_52_58>(4);
            _seatButtonsList2.Add(Oceanside.SplitWindow.SeatPosition1_2);
            _seatButtonsList2.Add(Oceanside.SplitWindow.SeatPosition2_2);
            _seatButtonsList2.Add(Oceanside.SplitWindow.SeatPosition3_2);
            _seatButtonsList2.Add(Oceanside.SplitWindow.SeatPosition4_2);

            ///Set the event handlers
            SplitWindow.ScrollSeatLeft.OnFlatButtonClicked +=
                new RoutedEventHandler(buttonScrollSeatLeft_Click_NOTHROW);
            SplitWindow.ScrollSeatRight.OnFlatButtonClicked +=
                new RoutedEventHandler(buttonScrollSeatRight_Click_NOTHROW);

            SplitWindow.ScrollSeatLeft2.OnFlatButtonClicked +=
                new RoutedEventHandler(buttonScrollSeatLeft2_Click_NOTHROW);
            SplitWindow.ScrollSeatRight2.OnFlatButtonClicked +=
                new RoutedEventHandler(buttonScrollSeatRight2_Click_NOTHROW);

            ///Wire in the event handlers for the seat position buttons.
            SplitWindow.SeatPosition1.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);
            SplitWindow.SeatPosition2.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);
            SplitWindow.SeatPosition3.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);
            SplitWindow.SeatPosition4.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat_Click_NOTHROW);

            SplitWindow.SeatPosition1_2.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat2_Click_NOTHROW);
            SplitWindow.SeatPosition2_2.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat2_Click_NOTHROW);
            SplitWindow.SeatPosition3_2.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat2_Click_NOTHROW);
            SplitWindow.SeatPosition4_2.OnFlatButtonClicked += new RoutedEventHandler(buttonSeat2_Click_NOTHROW);

            SplitWindow.ExitButton.MouseDown += new System.Windows.Input.MouseButtonEventHandler(ExitButton_MouseDown);

            SplitWindow.NewSeat2.MouseDown += new System.Windows.Input.MouseButtonEventHandler(NewSeat2_MouseDown);
            SplitWindow.NewSeat.MouseDown += new System.Windows.Input.MouseButtonEventHandler(NewSeat_MouseDown);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void NewSeat_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            NewSeatClicked();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void NewSeat2_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            NewSeat2Clicked();
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        static void ExitButton_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (CurrentFormMode == SPLITMODE.SEAT)
            {
                Oceanside.OrderApi.Show();
            }
            else
            {
                Oceanside.CloseCheckWindow.Show();
            }
        }

        static void CustomerTicketListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                int idx = (sender as ListView).SelectedIndex;

                ///Make sure this does not return a negative numTimes.  When we are in the middle
                ///of processing an event after a delete, this selected index change event will
                ///fire even though we have not updated the selected index yet.
                if (idx >= 0)
                {
                    _custTicketScrollIndex = idx;
                    _selectedSale = SplitWindow.CustomerTicketListView.Items[idx] as SALE;
                    if (_selectedSale != null && _selectedSale.IsExceptionModifier || _selectedSale.IsForcedModifier)
                    {
                        SplitWindow.CustomerTicketListView.SelectedItem = _selectedSale.PARENTSALE_WHEN_MODSALE;
                    }
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_CUST_TICKET_SELECTION_CHANGED, exc);
            }
        }

        static void CustomerTicketListView2_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                int idx = (sender as ListView).SelectedIndex;

                ///Make sure this does not return a negative numTimes.  When we are in the middle
                ///of processing an event after a delete, this selected index change event will
                ///fire even though we have not updated the selected index yet.
                if (idx >= 0)
                {
                    _custTicketScrollIndex2 = idx;
                    _selectedSale2 = SplitWindow.CustomerTicketListView2.Items[idx] as SALE;
                    if (_selectedSale2 != null && _selectedSale2.IsExceptionModifier || _selectedSale2.IsForcedModifier)
                    {
                        SplitWindow.CustomerTicketListView2.SelectedItem = _selectedSale2.PARENTSALE_WHEN_MODSALE;
                    }
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_CUST_TICKET_SELECTION_CHANGED, exc);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public static void PrepareForScreenChange_NOTHROW()
        {
            try
            {
                _selectedSeatIndex = 0;
                _seatPivotIndex = 0;

                _selectedSeatIndex2 = 0;
                _seatPivotIndex2 = 0;

                if (CurrentFormMode == SPLITMODE.SEAT)
                {
                    SplitWindow.NewSeat.ButtonLabelText = "New Seat";
                    SplitWindow.NewSeat2.ButtonLabelText = "New Seat";
                }
                else
                {
                    SplitWindow.NewSeat.ButtonLabelText = "New Check";
                    SplitWindow.NewSeat2.ButtonLabelText = "New Check";
                }

                SetScrollableSeatButtonsDataContext();
                SetScrollableSeatButtonsDataContext2();
                SetSeatTags();
                SetSeatTags2();
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_PREPARE_FOR_SCREEN_CHANGE, exc);
            }
        }


        public static void PrepareForScreenLeave_NOTHROW()
        {
            SelectedSale = null;
            SelectedSale2 = null;
        }

        /// <summary>
        /// This function is called when a seat scroll, addition or button click has
        /// caused an event.
        /// </summary>
        /// <param Name="newIndex"></param>
        public static void SeatChangeOccured(int newIndex)
        {
            if (newIndex != _selectedSeatIndex)
            {
                int count = 0;
                if (CurrentFormMode == SPLITMODE.SEAT)
                {
                    count = SHIFT.SelectedOrder.GuestCount;
                }
                else
                {
                    count = SHIFT.SelectedOrder.CheckCount;
                }

                ///Update the selected index and selected seat, but first assure it is in bounds.
                if (newIndex >= 0 && newIndex < count)
                {
                    ///Reset the line items scroll index on the customer ticket since we are
                    ///switching to a different seat.
                    _custTicketScrollIndex = 0;

                    ///Update the selected seat index.
                    _selectedSeatIndex = newIndex;
                    _selectedSale = null;
                    UpdateTicketFocus();
                }
            }
        }

        /// <summary>
        /// This function is called when a seat scroll, addition or button click has
        /// caused an event.
        /// </summary>
        /// <param Name="newIndex"></param>
        public static void SeatChangeOccured2(int newIndex)
        {
            if (newIndex != _selectedSeatIndex2)
            {
                int count = 0;
                if (CurrentFormMode == SPLITMODE.SEAT)
                {
                    count = SHIFT.SelectedOrder.GuestCount;
                }
                else
                {
                    count = SHIFT.SelectedOrder.CheckCount;
                }

                ///Update the selected index and selected seat, but first assure it is in bounds.
                if (newIndex >= 0 && newIndex < count)
                {
                    ///Reset the line items scroll index on the customer ticket since we are
                    ///switching to a different seat.
                    _custTicketScrollIndex2 = 0;

                    ///Update the selected seat index.
                    _selectedSeatIndex2 = newIndex;
                    _selectedSale2 = null;
                    UpdateTicketFocus2();
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private static void SetSeatTags()
        {
            int count = 0;
            if (CurrentFormMode == SPLITMODE.SEAT)
            {
                count = SHIFT.SelectedOrder.GuestCount;
            }
            else
            {
                count = SHIFT.SelectedOrder.CheckCount;
            }

            int i = count - _selectedSeatIndex;
            int numBlanks = Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA - i;

            int seatNumber = (_selectedSeatIndex + 1);
            if (count <= Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
            {
                seatNumber = 1;
            }
            else if (numBlanks > 0)
            {
                seatNumber = seatNumber - numBlanks;
            }

            foreach (FlatButton_52_58 s in _seatButtonsList)
            {
                if (seatNumber > count)
                {
                    s.LabelNumber = 0;
                    s.LabelString = null;
                }
                else
                {
                    s.LabelNumber = seatNumber;
                    s.LabelString = CurrentFormMode == SPLITMODE.SEAT ? "Seat\n" : "Check\n";
                    s.LabelString = s.LabelString + seatNumber;
                    seatNumber += 1;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private static void SetSeatTags2()
        {
            int count = 0;
            if (CurrentFormMode == SPLITMODE.SEAT)
            {
                count = SHIFT.SelectedOrder.GuestCount;
            }
            else
            {
                count = SHIFT.SelectedOrder.CheckCount;
            }

            int i = count - _selectedSeatIndex2;
            int numBlanks = Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA - i;

            int seatNumber2 = (_selectedSeatIndex2 + 1);
            if (count <= Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
            {
                seatNumber2 = 1;
            }
            else if (numBlanks > 0)
            {
                seatNumber2 = seatNumber2 - numBlanks;
            }

            foreach (FlatButton_52_58 s in _seatButtonsList2)
            {
                if (seatNumber2 > count)
                {
                    s.LabelNumber = 0;
                    s.LabelString = null;
                }
                else
                {
                    s.LabelNumber = seatNumber2;
                    s.LabelString = CurrentFormMode == SPLITMODE.SEAT ? "Seat\n" : "Check\n";
                    s.LabelString = s.LabelString + seatNumber2;
                    seatNumber2 += 1;
                }
            }
        }

        /// <summary>
        /// Handles when a seat itself has been clicked rather than a scroller.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonSeat_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            try
            {
                int count = 0;
                if (CurrentFormMode == SPLITMODE.SEAT)
                {
                    count = SHIFT.SelectedOrder.GuestCount;
                }
                else
                {
                    count = SHIFT.SelectedOrder.CheckCount;
                }

                FlatButton_52_58 b = (Oceanside.FlatButton_52_58)e.Source;

                if (null != b)
                {
                    int zeroBasedIndx = ((int)b.LabelNumber) - 1;
                    if (zeroBasedIndx < count && zeroBasedIndx >= 0)
                    {
                        SeatChangeOccured(zeroBasedIndx);
                        foreach (FlatButton_52_58 seat in _seatButtonsList)
                        {
                            seat.Unselect();
                        }
                        b.Select();
                        SetScrollableSeatButtonsDataContext(false);
                    }
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SEAT_BUTTON_CLICK, exc);
            }
        }

        /// <summary>
        /// Handles when a seat itself has been clicked rather than a scroller.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonSeat2_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            try
            {
                int count = 0;
                if (CurrentFormMode == SPLITMODE.SEAT)
                {
                    count = SHIFT.SelectedOrder.GuestCount;
                }
                else
                {
                    count = SHIFT.SelectedOrder.CheckCount;
                }

                FlatButton_52_58 b = (Oceanside.FlatButton_52_58)e.Source;

                if (null != b)
                {
                    int zeroBasedIndx = ((int)b.LabelNumber) - 1;
                    if (zeroBasedIndx < count && zeroBasedIndx >= 0)
                    {
                        SeatChangeOccured2(zeroBasedIndx);
                        foreach (FlatButton_52_58 seat in _seatButtonsList2)
                        {
                            seat.Unselect();
                        }
                        b.Select();
                        SetScrollableSeatButtonsDataContext2(false);
                    }
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SEAT_BUTTON_CLICK, exc);
            }
        }

        /// <summary>
        /// Will scroll the seats to the right if possible
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonScrollSeatRight_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            try
            {
                e.Handled = true;
                int count = 0;
                if (CurrentFormMode == SPLITMODE.SEAT)
                {
                    count = SHIFT.SelectedOrder.GuestCount;
                }
                else
                {
                    count = SHIFT.SelectedOrder.CheckCount;
                }
                if (_selectedSeatIndex != (count - 1))
                {
                    if ((count - _seatPivotIndex) > Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
                    {
                        _seatPivotIndex += 1;
                    }
                    SeatChangeOccured(_selectedSeatIndex + 1);
                    SetSeatTags();
                    SetScrollableSeatButtonsDataContext();
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SCROLL_SEAT_RIGHT, exc);
            }
        }

        /// <summary>
        /// Will scroll the seats to the right if possible
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonScrollSeatRight2_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            try
            {
                e.Handled = true;
                int count = 0;
                if (CurrentFormMode == SPLITMODE.SEAT)
                {
                    count = SHIFT.SelectedOrder.GuestCount;
                }
                else
                {
                    count = SHIFT.SelectedOrder.CheckCount;
                }
                if (_selectedSeatIndex2 != (count - 1))
                {
                    if ((count - _seatPivotIndex2) > Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
                    {
                        _seatPivotIndex2 += 1;
                    }
                    SeatChangeOccured2(_selectedSeatIndex2 + 1);
                    SetSeatTags2();
                    SetScrollableSeatButtonsDataContext2();
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SCROLL_SEAT_RIGHT, exc);
            }
        }

        /// <summary>
        /// Scroll the seats to the left if possible.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonScrollSeatLeft_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            try
            {
                if (_selectedSeatIndex != 0)
                {
                    if ((_selectedSeatIndex - _seatPivotIndex) == 0)
                    {
                        _seatPivotIndex--;
                    }
                    SeatChangeOccured(_selectedSeatIndex - 1);
                    SetSeatTags();
                    SetScrollableSeatButtonsDataContext();
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SCROLL_SEAT_LEFT, exc);
            }
        }

        /// <summary>
        /// Scroll the seats to the left if possible.
        /// </summary>
        /// <param Name="sender"></param>
        /// <param Name="e"></param>
        static void buttonScrollSeatLeft2_Click_NOTHROW(object sender, RoutedEventArgs e)
        {
            e.Handled = true;
            try
            {
                if (_selectedSeatIndex2 != 0)
                {
                    if ((_selectedSeatIndex2 - _seatPivotIndex2) == 0)
                    {
                        _seatPivotIndex2--;
                    }
                    SeatChangeOccured2(_selectedSeatIndex2 - 1);
                    SetSeatTags2();
                    SetScrollableSeatButtonsDataContext2();
                }
                PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
            }
            catch (Exception exc)
            {
                Constants.ErrorDispatcher.Notify(Error.EType.E_POBIND_SCROLL_SEAT_LEFT, exc);
            }
        }

        /// <summary>
        /// This function assures that the scrollable seats display correctly.
        /// </summary>
        public static void SetScrollableSeatButtonsDataContext(bool updateSelction = true)
        {
            if (CurrentFormMode == SPLITMODE.SEAT)
            {
                SplitWindow.CustomerTicketListView.DataContext = SHIFT.SelectedOrder.GetSeatsSales(_selectedSeatIndex);
            }
            else
            {
                SplitWindow.CustomerTicketListView.DataContext = SHIFT.SelectedOrder.GetChecksSales(_selectedSeatIndex);
            }

            if (updateSelction)
            {
                for (int indx = 0; indx < Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA; indx++)
                {
                    if (indx == (_selectedSeatIndex - _seatPivotIndex))
                    {
                        _seatButtonsList[indx].Select();
                    }
                    else
                    {
                        _seatButtonsList[indx].Unselect();
                    }
                }
            }
        }

        /// <summary>
        /// This function assures that the scrollable seats display correctly.
        /// </summary>
        public static void SetScrollableSeatButtonsDataContext2(bool updateSelction = true)
        {
            if (CurrentFormMode == SPLITMODE.SEAT)
            {
                SplitWindow.CustomerTicketListView2.DataContext = SHIFT.SelectedOrder.GetSeatsSales(_selectedSeatIndex2);
            }
            else
            {
                SplitWindow.CustomerTicketListView2.DataContext = SHIFT.SelectedOrder.GetChecksSales(_selectedSeatIndex2);
            }

            if (updateSelction)
            {
                for (int indx = 0; indx < Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA; indx++)
                {
                    if (indx == (_selectedSeatIndex2 - _seatPivotIndex2))
                    {
                        _seatButtonsList2[indx].Select();
                    }
                    else
                    {
                        _seatButtonsList2[indx].Unselect();
                    }
                }
            }
        }

        public static void ProductMoved()
        {
            SplitWindow.CustomerTicketListView.UnselectAll();
            SplitWindow.CustomerTicketListView2.UnselectAll();
            SelectedSale = null;
            SelectedSale2 = null;
            UpdateTicketFocus();
            UpdateTicketFocus2();
            PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
        }

        /// <summary>
        /// Should be called whenever we delete an item from the customer ticket or
        /// add or scroll items.
        /// </summary>
        private static void UpdateTicketFocus(bool focusLastItem = false)
        {
            int loc = 0;
            try
            {
                List<SALE> sales = null;

                if (CurrentFormMode == SPLITMODE.SEAT)
                {
                    sales = SHIFT.SelectedOrder.GetSeatsSales(_selectedSeatIndex);
                    loc = 1;
                }
                else
                {
                    sales = SHIFT.SelectedOrder.GetChecksSales(_selectedSeatIndex);
                    loc = 1;
                }

                SplitWindow.CustomerTicketListView.DataContext = sales;
                loc = 2;
                SplitWindow.CustomerTicketListView.Items.Refresh();
                loc = 3;

                if (_custTicketScrollIndex >= sales.Count() || _custTicketScrollIndex < 0 || focusLastItem)
                {
                    loc = 4;
                    _custTicketScrollIndex = sales.Count() - 1;
                    loc = 5;
                    if (_custTicketScrollIndex < 0)
                    {
                        _custTicketScrollIndex = 0;
                    }
                }

                loc = 6;
                if (sales.Count() != 0)
                {
                    loc = 7;
                    SALE selSale = sales[_custTicketScrollIndex];
                    loc = 8;
                    SplitWindow.CustomerTicketListView.SelectedItem = selSale;
                    loc = 9;
                    SplitWindow.CustomerTicketListView.UpdateLayout();
                    loc = 10;
                    SplitWindow.CustomerTicketListView.ScrollIntoView(selSale);
                    loc = 11;
                }
            }
            catch (Exception ex)
            {
                Logging.LogMessage("SPLIT MODE = " + CurrentFormMode + Constants.NEWLINE);
                Logging.LogMessage("SPLIT COUNT = " + loc + Constants.NEWLINE);
                Logging.LogException(ex);
            }
        }

        /// <summary>
        /// Should be called whenever we delete an item from the customer ticket or
        /// add or scroll items.
        /// </summary>
        private static void UpdateTicketFocus2(bool focusLastItem = false)
        {
            List<SALE> sales = null;

            if (CurrentFormMode == SPLITMODE.SEAT)
            {
                sales = SHIFT.SelectedOrder.GetSeatsSales(_selectedSeatIndex2).ToList();
            }
            else
            {
                sales = SHIFT.SelectedOrder.GetChecksSales(_selectedSeatIndex2).ToList();
            }

            SplitWindow.CustomerTicketListView2.DataContext = sales;
            SplitWindow.CustomerTicketListView2.Items.Refresh();

            if (_custTicketScrollIndex2 >= sales.Count() || _custTicketScrollIndex2 < 0 || focusLastItem)
            {
                _custTicketScrollIndex2 = sales.Count - 1;
                if (_custTicketScrollIndex2 < 0)
                {
                    _custTicketScrollIndex2 = 0;
                }
            }

            if (sales.Count() != 0)
            {
                SALE selSale = sales[_custTicketScrollIndex2];
                SplitWindow.CustomerTicketListView2.SelectedItem = selSale;
                SplitWindow.CustomerTicketListView2.UpdateLayout();
                SplitWindow.CustomerTicketListView2.ScrollIntoView(selSale);
            }
        }

        /// <summary>
        /// A databound function that is bound at startup and handles new seat clicks
        /// </summary>
        public static void NewSeatClicked()
        {
            if (CurrentFormMode == SPLITMODE.SEAT)
            {
                SHIFT.SelectedOrder.GuestCount += 1;
                int seatCount = SHIFT.SelectedOrder.GuestCount;
                if (seatCount > Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
                {
                    _seatPivotIndex = seatCount - Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA;
                }

                ///Update the currently displayed seat to the new one just added.
                SeatChangeOccured(seatCount - 1);
            }
            else
            {
                SHIFT.SelectedOrder.CheckCount += 1;
                int checkCount = SHIFT.SelectedOrder.CheckCount;
                if (checkCount > Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
                {
                    _seatPivotIndex = checkCount - Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA;
                }

                ///Update the currently displayed seat to the new one just added.
                SeatChangeOccured(checkCount - 1);

            }
            ///Assure the scrollable seat buttons display correctly now that we have added a new
            ///seat.
            SetScrollableSeatButtonsDataContext();
            SetSeatTags();

            SetScrollableSeatButtonsDataContext2();
            SetSeatTags2();
            PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
        }

        /// <summary>
        /// A databound function that is bound at startup and handles new seat clicks
        /// </summary>
        public static void NewSeat2Clicked()
        {
            if (CurrentFormMode == SPLITMODE.SEAT)
            {
                SHIFT.SelectedOrder.GuestCount += 1;
                int seatCount = SHIFT.SelectedOrder.GuestCount;
                if (seatCount > Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
                {
                    _seatPivotIndex2 = seatCount - Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA;
                }

                ///Update the currently displayed seat to the new one just added.
                SeatChangeOccured2(seatCount - 1);
            }
            else
            {
                SHIFT.SelectedOrder.CheckCount += 1;
                int checkCount = SHIFT.SelectedOrder.CheckCount;
                if (checkCount > Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA)
                {
                    _seatPivotIndex2 = checkCount - Constants.CONST_SEATSCHECKS_PER_SCROLL_AREA;
                }

                ///Update the currently displayed seat to the new one just added.
                SeatChangeOccured2(checkCount - 1);
            }

            ///Assure the scrollable seat buttons display correctly now that we have added a new
            ///seat.
            SetScrollableSeatButtonsDataContext2();
            SetSeatTags2();

            SetScrollableSeatButtonsDataContext();
            SetSeatTags();
            PosWindow.RefreshVisibility(PosWindow.PROP_TYPE_ENUM.SPL);
        }

        /// <summary>
        /// Scrolls the customers ticket up and down.
        /// </summary>
        /// <param Name="directionUp"></param>
        public static void TicketScrollClicked(bool directionUp)
        {
            if (directionUp)
            {
                _custTicketScrollIndex -= Constants.CONST_LINE_ITEMS_PER_SPLIT_WINDOW_VIEW;

                ///Since we just went ahead and knocked off an entire view panels worth, we
                ///need to assure we didn't drive negative.
                if (_custTicketScrollIndex < 0)
                {
                    _custTicketScrollIndex = 0;
                }
            }
            else  ///Must be scroll down
            {
                _custTicketScrollIndex += Constants.CONST_LINE_ITEMS_PER_SPLIT_WINDOW_VIEW;

                ///Make sure we didn't go too far, correct if we did by placing the view 
                ///at the end.
                IEnumerable<SALE> seatsSales = null;
                if (CurrentFormMode == SPLITMODE.SEAT)
                {
                    seatsSales = SHIFT.SelectedOrder.GetSeatsSales(_selectedSeatIndex);
                }
                else
                {
                    seatsSales = SHIFT.SelectedOrder.GetChecksSales(_selectedSeatIndex);
                }

                if (_custTicketScrollIndex >= seatsSales.Count())
                {
                    _custTicketScrollIndex = seatsSales.Count() - 1;
                }
            }
            UpdateTicketFocus();
        }

        /// <summary>
        /// Scrolls the customers ticket up and down.
        /// </summary>
        /// <param Name="directionUp"></param>
        public static void TicketScrollClicked2(bool directionUp)
        {
            if (directionUp)
            {
                _custTicketScrollIndex2 -= Constants.CONST_LINE_ITEMS_PER_SPLIT_WINDOW_VIEW;

                ///Since we just went ahead and knocked off an entire view panels worth, we
                ///need to assure we didn't drive negative.
                if (_custTicketScrollIndex2 < 0)
                {
                    _custTicketScrollIndex2 = 0;
                }
            }
            else  ///Must be scroll down
            {
                _custTicketScrollIndex2 += Constants.CONST_LINE_ITEMS_PER_SPLIT_WINDOW_VIEW;

                ///Make sure we didn't go too far, correct if we did by placing the view 
                ///at the end.
                IEnumerable<SALE> seatsSales = null;
                if (CurrentFormMode == SPLITMODE.SEAT)
                {
                    seatsSales = SHIFT.SelectedOrder.GetSeatsSales(_selectedSeatIndex2);
                }
                else
                {
                    seatsSales = SHIFT.SelectedOrder.GetChecksSales(_selectedSeatIndex2);
                }
                if (_custTicketScrollIndex2 >= seatsSales.Count())
                {
                    _custTicketScrollIndex2 = seatsSales.Count() - 1;
                }
            }
            UpdateTicketFocus2();
        }
    }
}
